Index: sites/all/modules/contrib/panels/plugins/display_renderers/panels_renderer_editor.class.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP
<+><?php\n\n/**\n * @file\n * Class file to control the main Panels editor.\n */\n\nclass panels_renderer_editor extends panels_renderer_standard {\n\n  /**\n   * An array of AJAX commands to return. If populated it will automatically\n   * be used by the AJAX router.\n   */\n  var $commands = array();\n  var $admin = TRUE;\n\n  /**\n   * Set to true if edit links (for panes and regions) should not be displayed.\n   * This can be used for special edit modes such as layout change and layout\n   * builder that do not actually have real content.\n   */\n  var $no_edit_links = FALSE;\n  // -------------------------------------------------------------------------\n  // Display edit rendering.\n\n  function edit() {\n    $form_state = array(\n      'display' => &$this->display,\n      'renderer' => &$this,\n      'content_types' => $this->cache->content_types,\n      'no_redirect' => TRUE,\n      'display_title' => !empty($this->cache->display_title),\n      'cache key' => $this->display->cache_key,\n    );\n\n    $output = drupal_build_form('panels_edit_display_form', $form_state);\n    if (empty($form_state['executed']) || !empty($form_state['clicked_button']['preview'])) {\n      return $output;\n    }\n\n    if (!empty($form_state['clicked_button']['#save-display'])) {\n      drupal_set_message(t('Panel content has been updated.'));\n      panels_save_display($this->display);\n    }\n    else {\n      drupal_set_message(t('Your changes have been discarded.'));\n    }\n\n    panels_cache_clear('display', $this->display->did);\n    return $this->display;\n  }\n\n  function add_meta() {\n    parent::add_meta();\n    if ($this->admin) {\n      ctools_include('ajax');\n      ctools_include('modal');\n      ctools_modal_add_js();\n\n      ctools_add_js('panels-base', 'panels');\n      ctools_add_js('display_editor', 'panels');\n      ctools_add_css('panels_dnd', 'panels');\n      ctools_add_css('panels_admin', 'panels');\n    }\n  }\n\n  function render() {\n    // Pass through to normal rendering if not in admin mode.\n    if (!$this->admin) {\n      return parent::render();\n    }\n\n    $this->add_meta();\n\n    $output = '<div class=\"panels-dnd\" id=\"panels-dnd-main\">';\n    $output .= $this->render_layout();\n    $output .= '</div>';\n\n    return $output;\n  }\n\n  function render_region($region_id, $panes) {\n    // Pass through to normal rendering if not in admin mode.\n    if (!$this->admin) {\n      return parent::render_region($region_id, $panes);\n    }\n\n    $content = implode('', $panes);\n\n    $panel_buttons = $this->get_region_links($region_id);\n\n    $output = \"<div class='panel-region' id='panel-region-$region_id'>\";\n    $output .= $panel_buttons;\n    $output .= \"<h2 class='label'>\" . check_plain($this->plugins['layout']['regions'][$region_id]) . \"</h2>\";\n    $output .= $content;\n    $output .= \"</div>\";\n\n    return $output;\n  }\n\n  function render_pane(&$pane) {\n    // Pass through to normal rendering if not in admin mode.\n    if (!$this->admin) {\n      return parent::render_pane($pane);\n    }\n\n    ctools_include('content');\n    $content_type = ctools_get_content_type($pane->type);\n\n    // This is just used for the title bar of the pane, not the content itself.\n    // If we know the content type, use the appropriate title for that type,\n    // otherwise, set the title using the content itself.\n    $title = ctools_content_admin_title($content_type, $pane->subtype, $pane->configuration, $this->display->context);\n    if (!$title) {\n      $title = t('Deleted/missing content type @type', array('@type' => $pane->type));\n    }\n\n    $buttons = $this->get_pane_links($pane, $content_type);\n\n    // Render administrative buttons for the pane.\n\n    $block = new stdClass();\n    if (empty($content_type)) {\n      $block->title = '<em>' . t('Missing content type') . '</em>';\n      $block->content = t('This pane\\'s content type is either missing or has been deleted. This pane will not render.');\n    }\n    else {\n      $block = ctools_content_admin_info($content_type, $pane->subtype, $pane->configuration, $this->display->context);\n    }\n\n    $grabber_class = 'grab-title grabber';\n    // If there are region locks, add them.\n    if (!empty($pane->locks['type'])) {\n      if ($pane->locks['type'] == 'regions') {\n        $settings['Panels']['RegionLock'][$pane->pid] = $pane->locks['regions'];\n        drupal_add_js($settings, 'setting');\n      }\n      else if ($pane->locks['type'] == 'immovable') {\n        $grabber_class = 'grab-title not-grabber';\n      }\n    }\n\n    $output = '';\n    $class = 'panel-pane';\n\n    if (empty($pane->shown)) {\n      $class .= ' hidden-pane';\n    }\n\n    if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {\n      $class .= ' panel-pane-is-title';\n    }\n\n    $output = '<div class=\"' . $class . '\" id=\"panel-pane-' . $pane->pid . '\">';\n\n    if (!$block->title) {\n      $block->title = t('No title');\n    }\n\n    $output .= '<div class=\"' . $grabber_class . '\">';\n    if ($buttons) {\n      $output .= '<span class=\"buttons\">' . $buttons . '</span>';\n    }\n    $output .= '<span class=\"text\">' . $title . '</span>';\n    $output .= '</div>'; // grabber\n\n    $output .= '<div class=\"panel-pane-collapsible\">';\n    $output .= '<div class=\"pane-title\">' . $block->title . '</div>';\n    $output .= '<div class=\"pane-content\">' . filter_xss_admin(render($block->content)) . '</div>';\n    $output .= '</div>'; // panel-pane-collapsible\n\n    $output .= '</div>'; // panel-pane\n\n    return $output;\n  }\n\n  /**\n   * Get the style links.\n   *\n   * This is abstracted out since we have styles on both panes and regions.\n   */\n  function get_style_links($type, $id = NULL) {\n    $info = $this->get_style($type, $id);\n    $style = $info[0];\n    $conf = $info[1];\n\n    $style_title = isset($style['title']) ? $style['title'] : t('Default');\n\n    $style_links[] = array(\n      'title' => $style_title,\n      'attributes' => array('class' => array('panels-text')),\n    );\n\n    $style_links[] = array(\n      'title' => t('Change'),\n      'href' => $this->get_url('style-type', $type, $id),\n      'attributes' => array('class' => array('ctools-use-modal')),\n    );\n\n    $function = $type != 'pane' ? 'settings form' : 'pane settings form';\n    if (panels_plugin_get_function('styles', $style, $function)) {\n      $style_links[] = array(\n        'title' => t('Settings'),\n        'href' => $this->get_url('style-settings', $type, $id),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n    }\n\n    return $style_links;\n  }\n\n  /**\n   * Get the links for a panel display.\n   *\n   * This is abstracted out for easy ajax replacement.\n   */\n  function get_display_links() {\n    $links = array();\n\n    if (user_access('administer panels styles')) {\n      $style_links = $this->get_style_links('display');\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    if (user_access('use panels caching features')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $method = isset($this->display->cache['method']) ? $this->display->cache['method'] : 0;\n      $info = panels_get_cache($method);\n      $cache_method = isset($info['title']) ? $info['title'] : t('No caching');\n\n      $cache_links[] = array(\n        'title' => $cache_method,\n        'attributes' => array('class' => array('panels-text')),\n      );\n      $cache_links[] = array(\n        'title' => t('Change'),\n        'href' => $this->get_url('cache-method', 'display'),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n      if (panels_plugin_get_function('cache', $info, 'settings form')) {\n        $cache_links[] = array(\n          'title' => t('Settings'),\n          'href' => $this->get_url('cache-settings', 'display'),\n          'attributes' => array('class' => array('ctools-use-modal')),\n        );\n      }\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Caching') . '</span>' . theme_links(array('links' => $cache_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    return theme('ctools_dropdown', array('title' => t('Display settings'), 'links' => $links, 'class' => 'panels-display-links'));\n  }\n\n  /**\n   * Render the links to display when editing a region.\n   */\n  function get_region_links($region_id) {\n    if (!empty($this->no_edit_links)) {\n      return '';\n    }\n    $links = array();\n    $links[] = array(\n      'title' => t('Add content'),\n      'href' => $this->get_url('select-content', $region_id),\n      'attributes' => array(\n        'class' => array('ctools-use-modal'),\n      ),\n    );\n\n    if (user_access('administer panels styles')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $style_links = $this->get_style_links('region', $region_id);\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-addcontent.png', 'panels'))), 'links' => $links, 'image' => TRUE, 'class' => 'pane-add-link panels-region-links-' . $region_id));\n  }\n\n  /**\n   * Render the links to display when editing a pane.\n   */\n  function get_pane_links($pane, $content_type) {\n    if (!empty($this->no_edit_links)) {\n      return '';\n    }\n    $links = array();\n\n    if (!empty($pane->shown)) {\n      $links[] = array(\n        'title' => t('Disable this pane'),\n        'href' => $this->get_url('hide', $pane->pid),\n        'attributes' => array('class' => array('use-ajax')),\n      );\n    }\n    else {\n      $links[] = array(\n        'title' => t('Enable this pane'),\n        'href' => $this->get_url('show', $pane->pid),\n        'attributes' => array('class' => array('use-ajax')),\n      );\n    }\n\n    if (isset($this->display->title_pane) && $this->display->title_pane == $pane->pid) {\n      $links['panels-set-title'] = array(\n        'title' => t('&#x2713;Panel title'),\n        'html' => TRUE,\n      );\n    }\n    else {\n      $links['panels-set-title'] = array(\n        'title' => t('Panel title'),\n        'href' => $this->get_url('panel-title', $pane->pid),\n        'attributes' => array('class' => array('use-ajax')),\n      );\n    }\n\n    $subtype = ctools_content_get_subtype($content_type, $pane->subtype);\n\n    if (ctools_content_editable($content_type, $subtype, $pane->configuration)) {\n      $links[] = array(\n        'title' => isset($content_type['edit text']) ? $content_type['edit text'] : t('Settings'),\n        'href' => $this->get_url('edit-pane', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n    }\n\n    if (user_access('administer advanced pane settings')) {\n      $links[] = array(\n        'title' => t('CSS properties'),\n        'href' => $this->get_url('pane-css', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n    }\n\n    if (user_access('administer panels styles')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $style_links = $this->get_style_links('pane', $pane->pid);\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Style') . '</span>' . theme_links(array('links' => $style_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    if (user_access('administer pane access')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $contexts = $this->display->context;\n      // Make sure we have the logged in user context\n      if (!isset($contexts['logged-in-user'])) {\n        $contexts['logged-in-user'] = ctools_access_get_loggedin_context();\n      }\n\n      $visibility_links = array();\n\n      if (!empty($pane->access['plugins'])) {\n        foreach ($pane->access['plugins'] as $id => $test) {\n          $plugin = ctools_get_access_plugin($test['name']);\n          $access_title  = isset($plugin['title']) ? $plugin['title'] : t('Broken/missing access plugin %plugin', array('%plugin' => $test['name']));\n          $access_description = ctools_access_summary($plugin, $contexts, $test);\n\n          $visibility_links[] = array(\n            'title' => $access_description,\n            'href' => $this->get_url('access-configure-test', $pane->pid, $id),\n            'attributes' => array('class' => array('ctools-use-modal', 'panels-italic')),\n          );\n        }\n      }\n      if (empty($visibility_links)) {\n        $visibility_links[] = array(\n          'title' => t('No rules'),\n          'attributes' => array('class' => array('panels-text')),\n        );\n      }\n\n      $visibility_links[] = array(\n        'title' => t('Add new rule'),\n        'href' => $this->get_url('access-add-test', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n\n      $visibility_links[] = array(\n        'title' => t('Settings'),\n        'href' => $this->get_url('access-settings', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Visibility rules') . '</span>' . theme_links(array('links' => $visibility_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    if (user_access('use panels locks')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $lock_type = !empty($pane->locks['type']) ? $pane->locks['type'] : 'none';\n      switch ($lock_type) {\n        case 'immovable':\n          $lock_method = t('Immovable');\n          break;\n        case 'regions':\n          $lock_method = t('Regions');\n          break;\n        case 'none':\n        default:\n          $lock_method = t('No lock');\n          break;\n      }\n\n      $lock_links[] = array(\n        'title' => $lock_method,\n        'attributes' => array('class' => array('panels-text')),\n      );\n      $lock_links[] = array(\n        'title' => t('Change'),\n        'href' => $this->get_url('lock', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Locking') . '</span>' . theme_links(array('links' => $lock_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    if (panels_get_caches() && user_access('use panels caching features')) {\n      $links[] = array(\n        'title' => '<hr />',\n        'html' => TRUE,\n      );\n\n      $method = isset($pane->cache['method']) ? $pane->cache['method'] : 0;\n      $info = panels_get_cache($method);\n      $cache_method = isset($info['title']) ? $info['title'] : t('No caching');\n      $cache_links[] = array(\n        'title' => $cache_method,\n        'attributes' => array('class' => array('panels-text')),\n      );\n      $cache_links[] = array(\n        'title' => t('Change'),\n        'href' => $this->get_url('cache-method', $pane->pid),\n        'attributes' => array('class' => array('ctools-use-modal')),\n      );\n      if (panels_plugin_get_function('cache', $info, 'settings form')) {\n        $cache_links[] = array(\n          'title' => t('Settings'),\n          'href' => $this->get_url('cache-settings', $pane->pid),\n          'attributes' => array('class' => array('ctools-use-modal')),\n        );\n      }\n\n      $links[] = array(\n        'title' => '<span class=\"dropdown-header\">' . t('Caching') . '</span>' . theme_links(array('links' => $cache_links, 'attributes' => array(), 'heading' => array())),\n        'html' => TRUE,\n        'attributes' => array('class' => array('panels-sub-menu')),\n      );\n    }\n\n    $links[] = array(\n      'title' => '<hr />',\n      'html' => TRUE,\n    );\n\n    $links[] = array(\n      'title' => t('Remove'),\n      'href' => '#',\n      'attributes' => array(\n        'class' => array('pane-delete'),\n        'id' => \"pane-delete-panel-pane-$pane->pid\",\n      ),\n    );\n\n    return theme('ctools_dropdown', array('title' => theme('image', array('path' => ctools_image_path('icon-configure.png', 'panels'))), 'links' => $links, 'image' => TRUE));\n  }\n\n  // -----------------------------------------------------------------------\n  // Display edit AJAX callbacks and helpers.\n\n  /**\n   * Generate a URL path for the AJAX editor.\n   */\n  function get_url() {\n    $args = func_get_args();\n    $command = array_shift($args);\n    $url = 'panels/ajax/' . $this->plugin['name'] . '/' . $command . '/' . $this->display->cache_key;\n    if ($args) {\n      $url .= '/' . implode('/', $args);\n    }\n\n    return $url;\n  }\n\n  /**\n   * AJAX command to show a pane.\n   */\n  function ajax_show($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_ajax_render_error(t('Invalid pane id.'));\n    }\n\n    $this->display->content[$pid]->shown = TRUE;\n    panels_edit_cache_set($this->cache);\n\n    $this->command_update_pane($pid);\n  }\n\n  /**\n   * AJAX command to show a pane.\n   */\n  function ajax_hide($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_ajax_render_error(t('Invalid pane id.'));\n    }\n\n    $this->display->content[$pid]->shown = FALSE;\n    panels_edit_cache_set($this->cache);\n\n    $this->command_update_pane($pid);\n  }\n\n  /**\n   * AJAX command to present a dialog with a list of available content.\n   */\n  function ajax_select_content($region = NULL, $category = NULL) {\n    if (!array_key_exists($region, $this->plugins['layout']['regions'])) {\n      ctools_modal_render(t('Error'), t('Invalid input'));\n    }\n\n    $title = t('Add content to !s', array('!s' => $this->plugins['layout']['regions'][$region]));\n\n    $categories = $this->get_categories($this->cache->content_types);\n\n    if (empty($categories)) {\n      $output = t('There are no content types you may add to this display.');\n    }\n    else {\n      $output = theme('panels_add_content_modal', array('renderer' => $this, 'categories' => $categories, 'category' => $category, 'region' => $region));\n    }\n    $this->commands[] = ctools_modal_command_display($title, $output);\n  }\n\n  /**\n   * Return the category name and the category key of a given content\n   * type.\n   *\n   * @todo -- this should be in CTools.\n   */\n  function get_category($content_type) {\n    if (isset($content_type['top level'])) {\n      $category = 'root';\n    }\n    else if (isset($content_type['category'])) {\n      if (is_array($content_type['category'])) {\n        list($category, $weight) = $content_type['category'];\n      }\n      else {\n        $category = $content_type['category'];\n      }\n    }\n    else {\n      $category = t('Uncategorized');\n    }\n\n    return array(preg_replace('/[^a-z0-9]/', '-', strtolower($category)), $category);\n  }\n\n\n  /**\n   * Create a list of categories from all of the content type.\n   *\n   * @return array\n   *   An array of categories. Each entry in the array will also be an array\n   *   with 'title' as the printable title of the category, and 'content'\n   *   being an array of all content in the category. Each item in the 'content'\n   *   array contain the array plugin definition so that it can be later\n   *   found in the content array. They will be keyed by the title so that they\n   *   can be sorted.\n   */\n  function get_categories($content_types) {\n    $categories = array();\n    $category_names = array();\n\n    foreach ($content_types as $type_name => $subtypes) {\n      foreach ($subtypes as $subtype_name => $content_type) {\n        list($category_key, $category) = $this->get_category($content_type);\n\n        if (empty($categories[$category_key])) {\n          $categories[$category_key] = array(\n            'title' => $category,\n            'content' => array(),\n          );\n          $category_names[$category_key] = $category;\n        }\n\n        $content_title = filter_xss_admin($content_type['title']);\n\n        // Ensure content with the same title doesn't overwrite each other.\n        while (isset($categories[$category_key]['content'][$content_title])) {\n          $content_title .= '-';\n        }\n\n        $categories[$category_key]['content'][$content_title] = $content_type;\n        $categories[$category_key]['content'][$content_title]['type_name'] = $type_name;\n        $categories[$category_key]['content'][$content_title]['subtype_name'] = $subtype_name;\n      }\n    }\n\n    // Now sort\n    natcasesort($category_names);\n    foreach ($category_names as $category => $name) {\n      $output[$category] = $categories[$category];\n    }\n\n    return $output;\n  }\n\n  /**\n   * AJAX entry point to add a new pane.\n   */\n  function ajax_add_pane($region = NULL, $type_name = NULL, $subtype_name = NULL, $step = NULL) {\n    $content_type = ctools_get_content_type($type_name);\n    $subtype = ctools_content_get_subtype($content_type, $subtype_name);\n\n    if (!isset($step) || !isset($this->cache->new_pane)) {\n      $pane = panels_new_pane($type_name, $subtype_name, TRUE);\n      $this->cache->new_pane = &$pane;\n    }\n    else {\n      $pane = &$this->cache->new_pane;\n    }\n\n    $form_state = array(\n      'display' => &$this->cache->display,\n      'contexts' => $this->cache->display->context,\n      'pane' => &$pane,\n      'cache_key' => $this->display->cache_key,\n      'display cache' => &$this->cache,\n      'ajax' => TRUE,\n      'modal' => TRUE,\n      // This will force the system to not automatically render.\n      'modal return' => TRUE,\n      'commands' => array(),\n    );\n\n    $form_info = array(\n      'path' => $this->get_url('add-pane', $region, $type_name, $subtype_name, '%step'),\n      'show cancel' => TRUE,\n      'next callback' => 'panels_ajax_edit_pane_next',\n      'finish callback' => 'panels_ajax_edit_pane_finish',\n      'cancel callback' => 'panels_ajax_edit_pane_cancel',\n    );\n\n    $output = ctools_content_form('add', $form_info, $form_state, $content_type, $pane->subtype, $subtype, $pane->configuration, $step);\n\n    // If $rc is FALSE, there was no actual form.\n    if ($output === FALSE || !empty($form_state['complete'])) {\n      // References get blown away with AJAX caching. This will fix that.\n      $pane = $form_state['pane'];\n      unset($this->cache->new_pane);\n\n      // Add the pane to the display\n      $this->display->add_pane($pane, $region);\n      panels_edit_cache_set($this->cache);\n\n      // Tell the client to draw the pane\n      $this->command_add_pane($pane);\n\n      // Dismiss the modal.\n      $this->commands[] = ctools_modal_command_dismiss();\n    }\n    else if (!empty($form_state['cancel'])) {\n      // If cancelling, return to the activity.\n      list($category_key, $category) = $this->get_category($subtype);\n      $this->ajax_select_content($region, $category_key);\n    }\n    else {\n      // This overwrites any previous commands.\n      $this->commands = ctools_modal_form_render($form_state, $output);\n    }\n  }\n\n  /**\n   * AJAX entry point to edit a pane.\n   */\n  function ajax_edit_pane($pid = NULL, $step = NULL) {\n    if (empty($this->cache->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->cache->display->content[$pid];\n\n    $content_type = ctools_get_content_type($pane->type);\n    $subtype = ctools_content_get_subtype($content_type, $pane->subtype);\n\n    $form_state = array(\n      'display' => &$this->cache->display,\n      'contexts' => $this->cache->display->context,\n      'pane' => &$pane,\n      'display cache' => &$this->cache,\n      'ajax' => TRUE,\n      'modal' => TRUE,\n      'modal return' => TRUE,\n      'commands' => array(),\n    );\n\n    $form_info = array(\n      'path' => $this->get_url('edit-pane', $pid, '%step'),\n      'show cancel' => TRUE,\n      'next callback' => 'panels_ajax_edit_pane_next',\n      'finish callback' => 'panels_ajax_edit_pane_finish',\n      'cancel callback' => 'panels_ajax_edit_pane_cancel',\n    );\n\n    $output = ctools_content_form('edit', $form_info, $form_state, $content_type, $pane->subtype,  $subtype, $pane->configuration, $step);\n\n    // If $rc is FALSE, there was no actual form.\n    if ($output === FALSE || !empty($form_state['cancel'])) {\n      // Dismiss the modal.\n      $this->commands[] = ctools_modal_command_dismiss();\n    }\n    else if (!empty($form_state['complete'])) {\n      // References get blown away with AJAX caching. This will fix that.\n      $this->cache->display->content[$pid] = $form_state['pane'];\n\n      // Conditionally overwrite the context for this panel if present in the form state.\n      if (!empty($form_state['display_cache']->display->context)) {\n        $this->cache->display->context = $form_state['display_cache']->display->context;\n      }\n\n      panels_edit_cache_set($this->cache);\n      $this->command_update_pane($pid);\n      $this->commands[] = ctools_modal_command_dismiss();\n    }\n    else {\n      // This overwrites any previous commands.\n      $this->commands = ctools_modal_form_render($form_state, $output);\n    }\n  }\n\n  /**\n   * AJAX entry point to select which pane is currently the title.\n   *\n   * @param string $pid\n   *   The pane id for the pane object whose title state we're setting.\n   */\n  function ajax_panel_title($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_ajax_render_error(t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n\n    $old_title = !empty($this->display->title_pane) ? $this->display->title_pane : NULL;\n    $this->display->title_pane = $pid;\n\n    panels_edit_cache_set($this->cache);\n\n    $this->command_update_pane($pane);\n\n    if ($old_title && !empty($this->cache->display->content[$old_title])) {\n      $this->command_update_pane($this->cache->display->content[$old_title]);\n    }\n  }\n\n  /**\n   * AJAX entry point to configure the cache method for a pane or the display.\n   *\n   * @param string $pid\n   *   Either a pane id for a pane in the display, or 'display' to edit the\n   *   display cache settings.\n   */\n  function ajax_cache_method($pid = NULL) {\n    ctools_include('content');\n    // This lets us choose whether we're doing the display's cache or\n    // a pane's.\n    if ($pid == 'display') {\n      $conf = &$this->display->cache;\n      $title = t('Cache method for this display');\n    }\n    else if (!empty($this->display->content[$pid])) {\n      $pane = &$this->display->content[$pid];\n      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n      $conf = &$pane->cache;\n      $title = t('Cache method for !subtype_title', array('!subtype_title' => $subtype['title']));\n    }\n    else {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $form_state = array(\n      'display' => &$this->display,\n      'conf' => &$conf,\n      'title' => $title,\n      'ajax' => TRUE,\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_cache_method_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    // Preserve this; this way we don't actually change the method until they\n    // have saved the form.\n    $info = panels_get_cache($form_state['method']);\n    $function = panels_plugin_get_function('cache', $info, 'settings form');\n    if (!$function) {\n      $conf['method'] = $form_state['method'];\n      $conf['settings'] = array();\n      panels_edit_cache_set($this->cache);\n\n      $this->commands[] = ctools_modal_command_dismiss();\n\n      if ($pid != 'display') {\n        $this->command_update_pane($pane);\n      }\n      else {\n        $this->command_update_display_links();\n      }\n    }\n    else {\n      $this->cache->method = $form_state['method'];\n      panels_edit_cache_set($this->cache);\n      // send them to next form.\n      return $this->ajax_cache_settings($pid);\n    }\n  }\n\n  /**\n   * AJAX entry point to configure the cache settings for a pane or the display.\n   *\n   * @param string $pid\n   *   Either a pane id for a pane in the display, or 'display' to edit the\n   *   display cache settings.\n   */\n  function ajax_cache_settings($pid = 0) {\n    ctools_include('content');\n\n    // This lets us choose whether we're doing the display's cache or\n    // a pane's.\n    if ($pid == 'display') {\n      $conf = &$this->display->cache;\n      $title = t('Cache settings for this display');\n    }\n    else if (!empty($this->display->content[$pid])) {\n      $pane = &$this->display->content[$pid];\n      $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n      $conf = &$pane->cache;\n      $title = t('Cache settings for !subtype_title', array('!subtype_title' => $subtype['title']));\n    }\n    else {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    if (isset($this->cache->method) && (empty($conf['method']) || $conf['method'] != $this->cache->method)) {\n      $conf['method'] = $this->cache->method;\n      $info = panels_get_cache($conf['method']);\n      $conf['settings'] = isset($info['defaults']) ? $info['defaults'] : array();\n    }\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pid' => $pid,\n      'conf' => &$conf,\n      'ajax' => TRUE,\n      'title' => $title,\n      'url' => url($this->get_url('cache-settings', $pid), array('absolute' => TRUE)),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_cache_settings_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    panels_edit_cache_set($this->cache);\n\n    $this->commands[] = ctools_modal_command_dismiss();\n\n    if ($pid != 'display') {\n      $this->command_update_pane($pane);\n    }\n    else {\n      $this->command_update_display_links();\n    }\n  }\n\n  /**\n   * AJAX entry point to select the style for a display, region or pane.\n   *\n   * @param string $type\n   *   Either display, region or pane\n   * @param $pid\n   *   The pane id, if a pane. The region id, if a region.\n   */\n  function ajax_style_type($type, $pid = NULL) {\n    // This lets us choose whether we're doing the display's cache or\n    // a pane's.\n    switch ($type) {\n      case 'display':\n        $style = isset($this->display->panel_settings['style']) ? $this->display->panel_settings['style'] : 'default';\n        $title = t('Default style for this display');\n        break;\n\n      case 'region':\n        $style = isset($this->display->panel_settings[$pid]['style']) ? $this->display->panel_settings[$pid]['style'] : '-1'; // -1 signifies to use the default setting.\n        $title = t('Panel style for region \"!region\"', array('!region' => $this->plugins['layout']['regions'][$pid]));\n        break;\n\n      case 'pane':\n        ctools_include('content');\n        $pane = &$this->display->content[$pid];\n        $style = isset($pane->style['style']) ? $pane->style['style'] : 'default';\n        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n        $title = t('Pane style for \"!pane\"', array('!pane' => $subtype['title']));\n        break;\n\n      default:\n        ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n    $info = $this->get_style($type, $pid);\n    $style_plugin = $info[0];\n    $style_settings = $info[1];\n\n    // Backward compatibility: Translate old-style stylizer to new style\n    // stylizer.\n    if ($style == 'stylizer' && !empty($style_settings['style']) && $style_settings['style'] != '$') {\n      $style = 'stylizer:' . $style_settings['style'];\n    }\n\n    $form_state = array(\n      'display' => &$this->display,\n      'style' => $style,\n      'pane' => ($type == 'pane') ? $this->display->content[$pid] : NULL,\n      'title' => $title,\n      'ajax' => TRUE,\n      'type' => $type,\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_style_type_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    // Preserve this; this way we don't actually change the method until they\n    // have saved the form.\n    $style = panels_get_style($form_state['style']);\n    $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');\n    if (!$function) {\n      if (isset($this->cache->style)) {\n        unset($this->cache->style);\n      }\n\n      // If there's no settings form, just change the style and exit.\n      switch($type) {\n        case 'display':\n          $this->display->panel_settings['style'] = $form_state['style'];\n          if (isset($this->display->panel_settings['style_settings']['default'])) {\n            unset($this->display->panel_settings['style_settings']['default']);\n          }\n          break;\n\n        case 'region':\n          $this->display->panel_settings[$pid]['style'] = $form_state['style'];\n          if (isset($this->display->panel_settings['style_settings'][$pid])) {\n            unset($this->display->panel_settings['style_settings'][$pid]);\n          }\n          break;\n\n        case 'pane':\n          $pane->style['style'] = $form_state['style'];\n          if (isset($pane->style['settings'])) {\n            unset($pane->style['settings']);\n          }\n\n          break;\n      }\n      panels_edit_cache_set($this->cache);\n\n      $this->commands[] = ctools_modal_command_dismiss();\n\n      if ($type == 'pane') {\n        $this->command_update_pane($pane);\n      }\n      else if ($type == 'region') {\n        $this->command_update_region_links($pid);\n      }\n      else {\n        $this->command_update_display_links();\n      }\n    }\n    else {\n      if ($form_state['style'] != $form_state['old_style']) {\n        $this->cache->style = $form_state['style'];\n        panels_edit_cache_set($this->cache);\n      }\n\n      // send them to next form.\n      return $this->ajax_style_settings($type, $pid);\n    }\n  }\n\n  /**\n   * Get the appropriate style from the panel in the cache.\n   *\n   * Since we have styles for regions, panes and the display itself, and\n   * they are stored differently, we use this method to simplify getting\n   * style information into a way that's easy to cope with.\n   */\n  function get_style($type, $pid = '') {\n    if (isset($this->cache->style)) {\n      $style = panels_get_style($this->cache->style);\n      $defaults = isset($style['defaults']) ? $style['defaults'] : array();\n      // Get the &$conf variable based upon whose style we're editing.\n      switch ($type) {\n        case 'display':\n          $this->display->panel_settings['style'] = $this->cache->style;\n          $this->display->panel_settings['style_settings']['default'] = $defaults;\n          break;\n\n        case 'region':\n          $this->display->panel_settings[$pid]['style'] = $this->cache->style;\n          $this->display->panel_settings['style_settings'][$pid] = $defaults;\n          break;\n\n        case 'pane':\n          $pane = &$this->display->content[$pid];\n          $pane->style['style'] = $this->cache->style;\n          $pane->style['settings'] = $defaults;\n          $conf = &$pane->style['settings'];\n          break;\n      }\n    }\n    else {\n      switch ($type) {\n        case 'display':\n          $style = panels_get_style((!empty($this->display->panel_settings['style'])) ? $this->display->panel_settings['style'] : 'default');\n          break;\n\n        case 'region':\n          $style = panels_get_style((!empty($this->display->panel_settings[$pid]['style'])) ? $this->display->panel_settings[$pid]['style'] : '-1');\n          break;\n\n        case 'pane':\n          $pane = &$this->display->content[$pid];\n          $style = panels_get_style(!empty($pane->style['style']) ? $pane->style['style'] : 'default');\n          break;\n      }\n    }\n\n    // Set up our $conf reference.\n    switch ($type) {\n      case 'display':\n        $conf = &$this->display->panel_settings['style_settings']['default'];\n        break;\n\n      case 'region':\n        $conf = &$this->display->panel_settings['style_settings'][$pid];\n        break;\n\n      case 'pane':\n        ctools_include('content');\n        $pane = &$this->display->content[$pid];\n        $conf = &$pane->style['settings'];\n        break;\n    }\n\n    // Backward compatibility: Translate old-style stylizer to new style\n    // stylizer.\n    if ($style['name'] == 'stylizer' && !empty($conf['style']) && $conf['style'] != '$') {\n      $style = panels_get_style('stylizer:' . $conf['style']);\n    }\n\n    return array($style, &$conf);\n  }\n\n  /**\n   * AJAX entry point to configure the style for a display, region or pane.\n   *\n   * @param string $type\n   *   Either display, region or pane\n   * @param $pid\n   *   The pane id, if a pane. The region id, if a region.\n   */\n  function ajax_style_settings($type, $pid = '') {\n    $info = $this->get_style($type, $pid);\n    $style = $info[0];\n    $conf = &$info[1];\n\n    switch ($type) {\n      case 'display':\n        $title = t('Style settings for @style (display)', array('@style' => $style['title']));\n        break;\n\n      case 'region':\n        $title = t('Style settings for style @style (Region \"!region\")', array('@style' => $style['title'], '!region' => $this->plugins['layout']['regions'][$pid]));\n        break;\n\n      case 'pane':\n        ctools_include('content');\n        $pane = &$this->display->content[$pid];\n        $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n        $title = t('Style settings for style @style (Pane \"!pane\")', array('@style' => $style['title'], '!pane' => $subtype['title']));\n        break;\n    }\n\n    $form_state = array(\n      'display' => &$this->display,\n      'type' => $type,\n      'pid' => $pid,\n      'conf' => &$conf,\n      'style' => $style,\n      'ajax' => TRUE,\n      'title' => $title,\n      'url' => url($this->get_url('style-settings', $type, $pid), array('absolute' => TRUE)),\n      'renderer' => &$this,\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_style_settings_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    if (isset($this->cache->style)) {\n      unset($this->cache->style);\n    }\n\n    // Copy settings from form state back into the cache.\n    if(!empty($form_state['values']['settings'])) {\n      $this->cache->display->content[$pid]->style['settings'] = $form_state['values']['settings'];\n    }\n\n    panels_edit_cache_set($this->cache);\n\n    $this->commands[] = ctools_modal_command_dismiss();\n\n    if ($type == 'pane') {\n      $this->command_update_pane($pane);\n    }\n    else if ($type == 'region') {\n      $this->command_update_region_links($pid);\n    }\n    else {\n      $this->command_update_display_links();\n    }\n  }\n\n  /**\n   * AJAX entry point to configure CSS for a pane.\n   *\n   * @param $pid\n   *   The pane id to edit.\n   */\n  function ajax_pane_css($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pane' => &$pane,\n      'ajax' => TRUE,\n      'title' => t('Configure CSS on !subtype_title', array('!subtype_title' => $subtype['title'])),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_css_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    panels_edit_cache_set($this->cache);\n    $this->command_update_pane($pid);\n    $this->commands[] = ctools_modal_command_dismiss();\n  }\n\n  /**\n   * AJAX entry point to configure CSS for a pane.\n   *\n   * @param $pid\n   *   The pane id to edit.\n   */\n  function ajax_lock($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pane' => &$pane,\n      'ajax' => TRUE,\n      'title' => t('Configure lock on !subtype_title', array('!subtype_title' => $subtype['title'])),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_configure_pane_lock_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    panels_edit_cache_set($this->cache);\n    $this->command_update_pane($pid);\n    $this->commands[] = ctools_modal_command_dismiss();\n  }\n\n  /**\n   * AJAX entry point to configure access settings for a pane.\n   *\n   * @param $pid\n   *   The pane id to edit.\n   */\n  function ajax_access_settings($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pane' => &$pane,\n      'ajax' => TRUE,\n      'title' => t('Access settings on !subtype_title', array('!subtype_title' => $subtype['title'])),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_configure_access_settings_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    panels_edit_cache_set($this->cache);\n    $this->command_update_pane($pid);\n    $this->commands[] = ctools_modal_command_dismiss();\n  }\n\n  /**\n   * AJAX entry point for to add a visibility rule.\n   */\n  function ajax_access_add_test($pid = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pane' => &$pane,\n      'ajax' => TRUE,\n      'title' => t('Add visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_add_access_test_form', $form_state);\n    if (!empty($form_state['executed'])) {\n      // Set up the plugin in cache\n      $plugin = ctools_get_access_plugin($form_state['values']['type']);\n      $this->cache->new_plugin = ctools_access_new_test($plugin);\n      panels_edit_cache_set($this->cache);\n\n      // go to the next step.\n      return $this->ajax_access_configure_test($pid, 'add');\n    }\n\n    $this->commands = $output;\n  }\n\n  /**\n   * AJAX entry point for to configure vsibility rule.\n   */\n  function ajax_access_configure_test($pid = NULL, $id = NULL) {\n    if (empty($this->display->content[$pid])) {\n      ctools_modal_render(t('Error'), t('Invalid pane id.'));\n    }\n\n    $pane = &$this->display->content[$pid];\n    $subtype = ctools_content_get_subtype($pane->type, $pane->subtype);\n\n    // Set this up here because $id gets changed later.\n    $url = $this->get_url('access-configure-test', $pid, $id);\n\n    // If we're adding a new one, get the stored data from cache and\n    // add it. It's stored as a cache so that if this is closed\n    // we don't accidentally add an unconfigured plugin.\n    if ($id == 'add') {\n      $pane->access['plugins'][] = $this->cache->new_plugin;\n      $id = max(array_keys($pane->access['plugins']));\n    }\n    else if (empty($pane->access['plugins'][$id])) {\n      ctools_modal_render(t('Error'), t('Invalid test id.'));\n    }\n\n    $form_state = array(\n      'display' => &$this->display,\n      'pane' => &$pane,\n      'ajax' => TRUE,\n      'title' => t('Configure visibility rule for !subtype_title', array('!subtype_title' => $subtype['title'])),\n      'test' => &$pane->access['plugins'][$id],\n      'plugin' => ctools_get_access_plugin($pane->access['plugins'][$id]['name']),\n      'url' => url($url, array('absolute' => TRUE)),\n    );\n\n    $output = ctools_modal_form_wrapper('panels_edit_configure_access_test_form', $form_state);\n    if (empty($form_state['executed'])) {\n      $this->commands = $output;\n      return;\n    }\n\n    // Unset the new plugin\n    if (isset($this->cache->new_plugin)) {\n      unset($this->cache->new_plugin);\n    }\n\n    if (!empty($form_state['remove'])) {\n      unset($pane->access['plugins'][$id]);\n    }\n\n    panels_edit_cache_set($this->cache);\n    $this->command_update_pane($pid);\n    $this->commands[] = ctools_modal_command_dismiss();\n  }\n\n  /**\n   * AJAX Router function for layout owned AJAX calls.\n   *\n   * Layouts like the flexible layout builder need callbacks of their own.\n   * This allows those layouts to simply declare their callbacks and use\n   * them with $this->get_url('layout', $command).\n   */\n  function ajax_layout() {\n    $args = func_get_args();\n    if (empty($args)) {\n      return MENU_NOT_FOUND;\n    }\n\n    $command = array_shift($args);\n    if (empty($this->plugins['layout']['ajax'][$command]) || !function_exists($this->plugins['layout']['ajax'][$command])) {\n      return MENU_NOT_FOUND;\n    }\n\n    // Make sure the this is always available to the called functions.\n    array_unshift($args, $this);\n    return call_user_func_array($this->plugins['layout']['ajax'][$command], $args);\n  }\n\n  /**\n   * AJAX Router function for style owned AJAX calls.\n   *\n   * Styles like the stylizer need AJAX callbacks of their own. This\n   * allows the system to figure out which style is being referenced,\n   * load it, and execute the callback.\n   *\n   * This allows those layouts to simply declare their callbacks and use\n   * them using $this->get_url('style', $command, $type, $pid).\n   */\n  function ajax_style() {\n    $args = func_get_args();\n    if (count($args) < 3) {\n      return MENU_NOT_FOUND;\n    }\n\n    $command = array_shift($args);\n    $type = array_shift($args);\n    $pid = array_shift($args);\n\n    $info = $this->get_style($type, $pid);\n\n    $style = $info[0];\n    $conf = &$info[1];\n\n    if (empty($style['ajax'][$command]) || !function_exists($style['ajax'][$command])) {\n      return MENU_NOT_FOUND;\n    }\n\n    // Make sure the this is always available to the called functions.\n    $args = array_merge(array(&$this, $style, &$conf, $type, $pid), $args);\n    return call_user_func_array($style['ajax'][$command], $args);\n  }\n\n  // ------------------------------------------------------------------------\n  // AJAX command generators\n  //\n  // These are used to make sure that child implementations can control their\n  // own AJAX commands as needed.\n\n  /**\n   * Create a command array to redraw a pane.\n   */\n  function command_update_pane($pid) {\n    if (is_object($pid)) {\n      $pane = $pid;\n    }\n    else {\n      $pane = $this->display->content[$pid];\n    }\n\n    $this->commands[] = ajax_command_replace(\"#panel-pane-$pane->pid\", $this->render_pane($pane));\n    $this->commands[] = ajax_command_changed(\"#panel-pane-$pane->pid\", \"div.grab-title span.text\");\n  }\n\n  /**\n   * Create a command array to add a new pane.\n   */\n  function command_add_pane($pid) {\n    if (is_object($pid)) {\n      $pane = $pid;\n    }\n    else {\n      $pane = $this->display->content[$pid];\n    }\n\n    $this->commands[] = ajax_command_append(\"#panel-region-$pane->panel\", $this->render_pane($pane));\n    $this->commands[] = ajax_command_changed(\"#panel-pane-$pane->pid\", \"div.grab-title span.text\");\n  }\n\n  /**\n   * Create a command to update the links on a display after a change was made.\n   */\n  function command_update_display_links() {\n    $this->commands[] = ajax_command_replace('.panels-display-links', $this->get_display_links());\n  }\n\n  /**\n   * Create a command to update the links on a region after a change was made.\n   */\n  function command_update_region_links($id) {\n    $this->commands[] = ajax_command_replace('.panels-region-links-' . $id, $this->get_region_links($id));\n  }\n}\n\n/**\n * Handle the 'next' click on the add/edit pane form wizard.\n *\n * All we need to do is store the updated pane in the cache.\n */\nfunction panels_ajax_edit_pane_next(&$form_state) {\n  $form_state['display cache']->new_pane = $form_state['pane'];\n  panels_edit_cache_set($form_state['display cache']);\n}\n\n/**\n * Handle the 'finish' click on teh add/edit pane form wizard.\n *\n * All we need to do is set a flag so the return can handle adding\n * the pane.\n */\nfunction panels_ajax_edit_pane_finish(&$form_state) {\n  $form_state['complete'] = TRUE;\n  return;\n}\n\n/**\n * Handle the 'cancel' click on the add/edit pane form wizard.\n */\nfunction panels_ajax_edit_pane_cancel(&$form_state) {\n  $form_state['cancel'] = TRUE;\n  return;\n}\n\n// --------------------------------------------------------------------------\n// Forms for the editor object\n\n/**\n * Choose cache method form\n */\nfunction panels_edit_cache_method_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $conf = &$form_state['conf'];\n\n  // Set to 0 to ensure we get a selected radio.\n  if (!isset($conf['method'])) {\n    $conf['method'] = 0;\n  }\n\n  $caches = panels_get_caches();\n  if (empty($caches)) {\n    $form['markup'] = array('#value' => t('No caching options are available at this time. Please enable a panels caching module in order to use caching options.'));\n    return $form;\n  }\n\n  $options[0] = t('No caching');\n  foreach ($caches as $cache => $info) {\n    $options[$cache] = check_plain($info['title']);\n  }\n\n  $form['method'] = array(\n    '#prefix' => '<div class=\"no-float\">',\n    '#suffix' => '</div>',\n    '#type' => 'radios',\n    '#title' => t('Method'),\n    '#options' => $options,\n    '#default_value' => $conf['method'],\n  );\n\n  $form['submit'] = array(\n    '#type' => 'submit',\n    '#value' => t('Next'),\n  );\n  return $form;\n}\n\n/**\n * Submit callback for panels_edit_cache_method_form.\n *\n * All this needs to do is return the method.\n */\nfunction panels_edit_cache_method_form_submit($form, &$form_state) {\n  $form_state['method'] = $form_state['values']['method'];\n}\n\n/**\n * Cache settings form\n */\nfunction panels_edit_cache_settings_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $conf = &$form_state['conf'];\n  $pid = $form_state['pid'];\n  $info = panels_get_cache($conf['method']);\n\n  $form['#action'] = $form_state['url'];\n\n  $form['description'] = array(\n    '#prefix' => '<div class=\"description\">',\n    '#suffix' => '</div>',\n    '#value' => check_plain($info['description']),\n  );\n\n  $function = panels_plugin_get_function('cache', $conf['method'], 'settings form');\n\n  $form['settings'] = $function($conf['settings'], $display, $pid);\n  $form['settings']['#tree'] = TRUE;\n\n  $form['display'] = array(\n    '#type' => 'value',\n    '#value' => $display,\n  );\n\n  $form['pid'] = array(\n    '#type' => 'value',\n    '#value' => $pid,\n  );\n\n  $form['submit'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  return $form;\n}\n\n/**\n * Validate cache settings.\n */\nfunction panels_edit_cache_settings_form_validate($form, &$form_state) {\n  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form validate')) {\n    $function($form, $form_state['values']['settings']);\n  }\n}\n\n/**\n * Allows panel styles to validate their style settings.\n */\nfunction panels_edit_cache_settings_form_submit($form, &$form_state) {\n  if ($function = panels_plugin_get_function('cache', $form_state['conf']['method'], 'settings form submit')) {\n    $function($form_state['values']['settings']);\n  }\n\n  $form_state['conf']['settings'] = $form_state['values']['settings'];\n}\n\n/**\n * Choose style form\n */\nfunction panels_edit_style_type_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $style = $form_state['style'];\n  $type = $form_state['type'];\n\n  $styles = panels_get_styles();\n\n  $function = ($type == 'pane' ? 'render pane' : 'render region');\n  $options = array();\n  if ($type == 'region') {\n    $options[-1] = t('Use display default style');\n  }\n\n  uasort($styles, 'ctools_plugin_sort');\n\n  foreach ($styles as $id => $info) {\n    if (empty($info['hidden']) && (!empty($info[$function]) || $id == 'default')) {\n      $options[$id] = check_plain($info['title']);\n    }\n  }\n\n  $form['style'] = array(\n    '#prefix' => '<div class=\"no-float\">',\n    '#suffix' => '</div>',\n    '#type' => 'radios',\n    '#title' => t('Style'),\n    '#options' => $options,\n    '#default_value' => $style,\n  );\n\n  $form['submit'] = array(\n    '#type' => 'submit',\n    '#value' => t('Next'),\n  );\n  return $form;\n}\n\n/**\n * Submit callback for panels_edit_style_type_form.\n *\n * All this needs to do is return the method.\n */\nfunction panels_edit_style_type_form_submit($form, &$form_state) {\n  $form_state['old_style'] = $form_state['style'];\n  $form_state['style'] = $form_state['values']['style'];\n}\n\n/**\n * Style settings form\n */\nfunction panels_edit_style_settings_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $conf = &$form_state['conf'];\n  $pid = $form_state['pid'];\n  $style = $form_state['style'];\n  $type = $form_state['type'];\n\n  $form['#action'] = $form_state['url'];\n\n  $form['description'] = array(\n    '#prefix' => '<div class=\"description\">',\n    '#suffix' => '</div>',\n    '#value' => check_plain($style['description']),\n  );\n\n  $function = panels_plugin_get_function('styles', $style, ($type == 'pane') ? 'pane settings form' : 'settings form');\n\n  $form['settings'] = $function($conf, $display, $pid, $type, $form_state);\n  $form['settings']['#tree'] = TRUE;\n\n  $form['submit'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  return $form;\n}\n\n/**\n * Validate style settings.\n */\nfunction panels_edit_style_settings_form_validate($form, &$form_state) {\n  $name = $form_state['type'] == 'pane' ? 'pane settings form validate' : 'settings form validate';\n  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {\n    $function($form, $form_state['values']['settings'], $form_state);\n  }\n}\n\n/**\n * Allows panel styles to validate their style settings.\n */\nfunction panels_edit_style_settings_form_submit($form, &$form_state) {\n  $name = $form_state['type'] == 'pane' ? 'pane settings form submit' : 'settings form submit';\n  if ($function = panels_plugin_get_function('styles', $form_state['style'], $name)) {\n    $function($form, $form_state['values']['settings'], $form_state);\n  }\n\n  $form_state['conf'] = $form_state['values']['settings'];\n}\n\n\n/**\n * Configure CSS on a pane form.\n */\nfunction panels_edit_configure_pane_css_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $pane = &$form_state['pane'];\n\n  $form['css_id'] = array(\n    '#type' => 'textfield',\n    '#default_value' => isset($pane->css['css_id']) ? $pane->css['css_id'] : '',\n    '#title' => t('CSS ID'),\n    '#description' => t('CSS ID to apply to this pane. This may be blank.'),\n  );\n  $form['css_class'] = array(\n    '#type' => 'textfield',\n    '#default_value' => isset($pane->css['css_class']) ? $pane->css['css_class'] : '',\n    '#title' => t('CSS class'),\n    '#description' => t('CSS class to apply to this pane. This may be blank.'),\n  );\n\n  $form['next'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  return $form;\n}\n\n/**\n * FAPI submission function for the CSS configure form.\n *\n * All this does is set up $pane properly. The caller is responsible for\n * actually storing this somewhere.\n */\nfunction panels_edit_configure_pane_css_form_submit($form, &$form_state) {\n  $pane = &$form_state['pane'];\n  $display = $form_state['display'];\n\n  $pane->css['css_id'] = $form_state['values']['css_id'];\n  $pane->css['css_class'] = $form_state['values']['css_class'];\n}\n\n/**\n * Configure lock on a pane form.\n */\nfunction panels_edit_configure_pane_lock_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $pane = &$form_state['pane'];\n\n  if (empty($pane->locks)) {\n    $pane->locks = array('type' => 'none', 'regions' => array());\n  }\n\n  $form['type'] = array(\n    '#type' => 'radios',\n    '#title' => t('Lock type'),\n    '#options' => array(\n      'none' => t('No lock'),\n      'immovable' => t('Immovable'),\n      'regions' => t('Regions'),\n    ),\n    '#default_value' => $pane->locks['type'],\n  );\n\n  $layout = panels_get_layout($display->layout);\n  $regions = panels_get_regions($layout, $display);\n\n  $form['regions'] = array(\n    '#type' => 'checkboxes',\n    '#title' => t('Regions'),\n    '#options' => $regions,\n    '#description' => t('Select which regions this pane can be moved to.'),\n    '#dependency' => array(\n      'radio:type' => array('regions'),\n    ),\n    '#default_value' => $pane->locks['regions'],\n  );\n\n  $form['#after_build'][] = 'panels_edit_configure_pane_lock_form_after_build';\n  $form['next'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  return $form;\n}\n\nfunction panels_edit_configure_pane_lock_form_after_build($element, $form_state) {\n  $region = $form_state['pane']->panel;\n  $element['regions'][$region]['#required'] = TRUE;\n  $element['regions'][$region]['#disabled'] = TRUE;\n  $element['regions'][$region]['#value'] = TRUE;\n  $element['regions'][$region]['#checked'] = TRUE;\n  $element['regions'][$region]['#attributes']['disabled'] = TRUE;\n  return $element;\n}\n\n/**\n * FAPI submission function for the lock configure form.\n *\n * All this does is set up $pane properly. The caller is responsible for\n * actually storing this somewhere.\n */\nfunction panels_edit_configure_pane_lock_form_submit($form, &$form_state) {\n  $pane = &$form_state['pane'];\n  $display = $form_state['display'];\n\n  // We set this to true but forms do not submit disabled checkboxes\n  // and fapi is ignoring the #value directive probably because it\n  // is checkboxes:\n  $region = $form_state['pane']->panel;\n  $form_state['values']['regions'][$region] = $region;\n\n  $pane->locks['type'] = $form_state['values']['type'];\n  $pane->locks['regions'] = array_filter($form_state['values']['regions']);\n}\n\n/**\n * Form to control basic visibility settings.\n */\nfunction panels_edit_configure_access_settings_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $pane = &$form_state['pane'];\n\n  $form['logic'] = array(\n    '#type' => 'radios',\n    '#options' => array(\n      'and' => t('All criteria must pass.'),\n      'or' => t('Only one criterion must pass.'),\n    ),\n    '#default_value' => isset($pane->access['logic']) ? $pane->access['logic'] : 'and',\n  );\n\n  $form['next'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  return $form;\n}\n\n/**\n * FAPI submission function for the edit access settings form.\n *\n * All this does is set up $pane properly. The caller is responsible for\n * actually storing this somewhere.\n */\nfunction panels_edit_configure_access_settings_form_submit($form, &$form_state) {\n  $pane = &$form_state['pane'];\n  $display = $form_state['display'];\n\n  $pane->access['logic'] = $form_state['values']['logic'];\n}\n\n/**\n * Form to add a visibility rule.\n */\nfunction panels_edit_add_access_test_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $pane = &$form_state['pane'];\n\n  $plugins = ctools_get_relevant_access_plugins($display->context);\n  $options = array();\n  foreach ($plugins as $id => $plugin) {\n    $options[$id] = $plugin['title'];\n  }\n\n  asort($options);\n\n  $form['type'] = array(\n    // This ensures that the form item is added to the URL.\n    '#type' => 'radios',\n    '#options' => $options,\n  );\n\n  $form['next'] = array(\n    '#type' => 'submit',\n    '#value' => t('Next'),\n  );\n\n  return $form;\n}\n\n/**\n * Form to configure a visibility rule.\n */\nfunction panels_edit_configure_access_test_form($form, &$form_state) {\n  $display = &$form_state['display'];\n  $test = &$form_state['test'];\n  $plugin = &$form_state['plugin'];\n\n  $form['#action'] = $form_state['url'];\n\n  $contexts = $display->context;\n  if (!isset($contexts['logged-in-user'])) {\n    $contexts['logged-in-user'] = ctools_access_get_loggedin_context();\n  }\n\n  if (isset($plugin['required context'])) {\n    $form['context'] = ctools_context_selector($contexts, $plugin['required context'], $test['context']);\n  }\n\n  $form['settings'] = array('#tree' => TRUE);\n  if ($function = ctools_plugin_get_function($plugin, 'settings form')) {\n    $form = $function($form, $form_state, $test['settings']);\n  }\n\n  $form['not'] = array(\n    '#type' => 'checkbox',\n    '#title' => t('Reverse (NOT)'),\n    '#default_value' => !empty($test['not']),\n  );\n\n  $form['save'] = array(\n    '#type' => 'submit',\n    '#value' => t('Save'),\n  );\n\n  $form['remove'] = array(\n    '#type' => 'submit',\n    '#value' => t('Remove'),\n    '#remove' => TRUE,\n  );\n\n  return $form;\n}\n\n/**\n * Validate handler for visibility rule settings\n */\nfunction panels_edit_configure_access_test_form_validate(&$form, &$form_state) {\n  if (!empty($form_state['clicked_button']['#remove'])) {\n    return;\n  }\n\n  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form validate')) {\n    $function($form, $form_state);\n  }\n}\n\n/**\n * Submit handler for visibility rule settings\n */\nfunction panels_edit_configure_access_test_form_submit(&$form, &$form_state) {\n  if (!empty($form_state['clicked_button']['#remove'])) {\n    $form_state['remove'] = TRUE;\n    return;\n  }\n\n  if ($function = ctools_plugin_get_function($form_state['plugin'], 'settings form submit')) {\n    $function($form, $form_state);\n  }\n\n  $form_state['test']['settings'] = $form_state['values']['settings'];\n  if (isset($form_state['values']['context'])) {\n    $form_state['test']['context'] = $form_state['values']['context'];\n  }\n  $form_state['test']['not'] = !empty($form_state['values']['not']);\n}\n\n
===================================================================
--- sites/all/modules/contrib/panels/plugins/display_renderers/panels_renderer_editor.class.php	(revision 1744d67ab2d7a37ecb8120faa9362eff51fb2f50)
+++ sites/all/modules/contrib/panels/plugins/display_renderers/panels_renderer_editor.class.php	(revision )
@@ -161,7 +161,7 @@
     if ($buttons) {
       $output .= '<span class="buttons">' . $buttons . '</span>';
     }
-    $output .= '<span class="text">' . $title . '</span>';
+    $output .= '<span class="text" title="' . htmlentities($title) . '">' . $title . '</span>';
     $output .= '</div>'; // grabber
 
     $output .= '<div class="panel-pane-collapsible">';
